package com.chengcang.api.modules.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chengcang.api.modules.sys.dao.SysProductDao;
import com.chengcang.api.modules.sys.dao.SysProductTypeDao;
import com.chengcang.api.modules.sys.dto.SysDictDataDTO;
import com.chengcang.api.modules.sys.dto.SysProductDTO;
import com.chengcang.api.modules.sys.entity.SysProductEntity;
import com.chengcang.api.modules.sys.entity.SysProductTypeEntity;
import com.chengcang.api.modules.sys.service.SysProductService;
import com.chengcang.api.modules.sys.service.SysProductTypeService;
import com.chengcang.api.modules.sys.vo.SysProductSeriesVo;
import com.chengcang.common.constant.Constant;
import com.chengcang.common.page.PageData;
import com.chengcang.common.service.impl.CrudServiceImpl;
import com.chengcang.common.utils.ConvertUtils;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author Mark sunlightcs@gmail.com
 * @since 1.0.0 2023-01-10
 */
@Service
@Slf4j
public class SysProductServiceImpl extends CrudServiceImpl<SysProductDao, SysProductEntity, SysProductDTO> implements SysProductService {

    @Autowired
    private SysProductDao sysProductDao;

    @Autowired
    private SysProductTypeService sysProductTypeService;

    @Autowired
    private SysProductTypeDao sysProductTypeDao;

    private static final String LEVEL = "level";

    private static final String PRODUCT_TYPE_ID = "product_type_id";

    @Override
    public QueryWrapper<SysProductEntity> getWrapper(Map<String, Object> params) {
        String id = (String) params.get("id");
        QueryWrapper<SysProductEntity> wrapper = new QueryWrapper<>();
        //二级
        if (params.get(LEVEL) != null && params.get(LEVEL).equals(1)) {
            wrapper.eq(StringUtils.isNotBlank(id), PRODUCT_TYPE_ID, id);
        } else if (params.get(LEVEL) != null && params.get(LEVEL).equals("0")) {
            List<Long> secondIdsById = sysProductTypeService.getSecondIdsById(Long.parseLong(id));
            wrapper.in(secondIdsById.size() != 0, PRODUCT_TYPE_ID, secondIdsById);
        }
        return wrapper;
    }


    @Override
    public PageData<SysProductDTO> getlist(Map<String, Object> params) {
        long id = Long.parseLong((String) params.get("id"));
        int pageIndex = checkAndParseInt(params.get(Constant.PAGE));
        int pageSize = checkAndParseInt(params.get(Constant.LIMIT));
        int level = checkAndParseInt(params.get("level"));
        if (level == 0) {
            return new PageData<SysProductDTO>(sysProductDao.getList((pageIndex - 1) * pageSize, pageSize, id),
                    sysProductDao.count((pageIndex - 1) * pageSize, pageSize, (long) id));
        } else if (level == 1) {
            return page(params);
        }
        return null;
    }


    @Override
    public SysProductDTO getDetail(Long id) {
        return sysProductDao.getDetail(id);
    }

    @Override
    public List<SysDictDataDTO> getSpec(Long id) {
        LambdaQueryWrapper<SysProductEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysProductEntity::getId, id).eq(SysProductEntity::getDeleted, 0)
                .select(SysProductEntity::getSpec, SysProductEntity::getId);
        SysProductEntity sysProductEntity = sysProductDao.selectOne(queryWrapper);
        List<SysDictDataDTO> sysDictDataEntities = new ArrayList<>();
        if (sysProductEntity != null && sysProductEntity.getSpec() != null) {
            for (String dictValue : sysProductEntity.getSpec().split(",")) {
                SysDictDataDTO dto = new SysDictDataDTO();
                dto.setDictValue(dictValue);
//                dto.setDictLabel(sysDictDataService.getValue(DataTypeEnum.PRODUCT_UNIT, dictValue));
                sysDictDataEntities.add(dto);
            }
        }
        //转换
        return sysDictDataEntities;

    }

    @Override
    public Page<SysProductDTO> getPage(Map<String, Object> params) {
        Page<SysProductDTO> result = new Page<>();
        QueryWrapper<SysProductEntity> queryWrapper = getWrapper(params);
        Object order = params.get(Constant.ORDER_FIELD);
        queryWrapper.last(params.get("condition") != null,
                        String.format("AND (code like '%%%s%%' or name like '%%%s%%')", params.get("condition"), params.get("condition")))
                .orderBy(order != null, params.get(Constant.ORDER) == null, (String) order);
        Page<SysProductEntity> sysProductEntityPage = sysProductDao.selectPage(new Page<>(Long.parseLong((String) params.get(Constant.PAGE)),
                Long.parseLong((String) params.get(Constant.LIMIT))), queryWrapper);

        BeanUtils.copyProperties(sysProductEntityPage, result);
        result.setRecords(ConvertUtils.sourceToTarget(sysProductEntityPage.getRecords(), SysProductDTO.class));
        if (sysProductEntityPage.getRecords() != null && sysProductEntityPage.getRecords().size() != 0) {
            //二级
            List<SysProductTypeEntity> secondTypes = sysProductTypeDao.selectBatchIds(result.getRecords().stream()
                    .map(SysProductDTO::getProductTypeId).distinct().collect(Collectors.toList()));
            //二级map
            Map<Long, SysProductTypeEntity> secondTypeMaps = secondTypes.stream()
                    .collect(Collectors.toMap(SysProductTypeEntity::getId, item -> {
                        return item;
                    }));
            //一级map
            Map<Long, String> firstTypeMaps = null;
            List<Long> second = secondTypes.stream().map(SysProductTypeEntity::getPid)
                    .distinct().collect(Collectors.toList());
            if(!second.isEmpty()){
                List<SysProductTypeEntity> sysProductTypeEntityList = sysProductTypeDao.selectBatchIds(second);
                if(!sysProductTypeEntityList.isEmpty()){
                    firstTypeMaps = sysProductTypeEntityList.stream().collect(Collectors.toMap(SysProductTypeEntity::getId,
                            SysProductTypeEntity::getName, (key1, kye2) -> {
                                return key1;
                            }));
                }
            }

            for (SysProductDTO record : result.getRecords()) {
                //二级
                SysProductTypeEntity secondType = secondTypeMaps.get(record.getProductTypeId());
                if (secondType != null) {
                    //second tupe name
                    record.setSecondParentName(secondType.getName());
                    //first type id
                    record.setFirstParentId(secondType.getPid());
                    //first type name
                    if (firstTypeMaps !=null && firstTypeMaps.size() != 0) record.setFirstParentName(firstTypeMaps.get(secondType.getPid()));
                }
            }
            List<SysProductDTO> records = result.getRecords();
            Map<String, String> specDictMap = getSpecByIds(records.stream().map(SysProductDTO::getId).collect(Collectors.toList())).stream().filter(item -> {
                return item.getDictValue() != null && item.getDictLabel() != null;
            }).collect(Collectors.toMap(SysDictDataDTO::getDictValue, SysDictDataDTO::getDictLabel, (key1, kye2) -> {
                return key1;
            }));
            //产品规格字典
            for (SysProductDTO sysProductDTO : records) {
                if (sysProductDTO != null && sysProductDTO.getSpec() != null) {
                    StringBuilder str = new StringBuilder();
                    for (String dictValue : sysProductDTO.getSpec().split(",")) {
                        str.append(specDictMap.get(dictValue)).append(",");
                    }
                    sysProductDTO.setSpecDesc(str.substring(0, str.length() - 1));
                }
            }
        }


        return result;
    }

    public List<SysDictDataDTO> getSpecByIds(List<Long> ids) {
        List<SysDictDataDTO> sysDictDataEntities = new ArrayList<>();
        LambdaQueryWrapper<SysProductEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(SysProductEntity::getId, ids).eq(SysProductEntity::getDeleted, 0)
                .select(SysProductEntity::getSpec, SysProductEntity::getId);
        List<SysProductEntity> sysProductEntitys = sysProductDao.selectList(queryWrapper);
        for (SysProductEntity sysProductEntity : sysProductEntitys) {
            if (sysProductEntity != null && sysProductEntity.getSpec() != null) {
                for (String dictValue : sysProductEntity.getSpec().split(",")) {
                    SysDictDataDTO dto = new SysDictDataDTO();
                    dto.setDictValue(dictValue);
                    //dto.setDictLabel(sysDictDataService.getValue(DataTypeEnum.PRODUCT_UNIT, dictValue));
                    sysDictDataEntities.add(dto);
                }
            }
        }
        return sysDictDataEntities;
    }

    @Override
    public void batchUpdate(List<SysProductDTO> dto) {
        try {
            ArrayList<SysProductEntity> productist = Lists.newArrayListWithCapacity(dto.size());
            dto.forEach(item -> {
                SysProductEntity sysProductEntity = new SysProductEntity();
                BeanUtils.copyProperties(item, sysProductEntity);
                productist.add(sysProductEntity);
            });
            this.updateBatchById(productist);
        } catch (Exception e) {
            throw new RuntimeException("批量更新异常!");
        }
    }

    @Override
    public List<SysProductSeriesVo> getSeriesProductByIds(List<Long> ids) {
        return sysProductDao.getSeriesProductByIds(ids);
    }

    private int checkAndParseInt(Object str) {
        int result;
        if (str != null && str != "") {
            result = Integer.parseInt(str.toString());
        } else {
            throw new IllegalArgumentException("param  is illegal!");
        }
        return result;
    }
}
